﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Reflection;

namespace Middleware.ApiTest.Attributes
{
    /// <summary>
    /// 数据脱敏特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class DataMaskingAttribute : Attribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // 方法执行前
            Console.WriteLine("脱敏处理方法执行....");
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            Console.WriteLine("业务方法执行后，获取结果开始对数据脱敏处理...");
            if (context.Result is ObjectResult objectResult)
            {
                objectResult.Value = MaskSensitiveData(objectResult.Value);
            }
        }

        /// <summary>
        /// 脱敏处理（支持嵌套对象和集合）
        /// </summary>
        /// <param name="data">要处理的数据</param>
        /// <returns>脱敏后的数据</returns>
        private object MaskSensitiveData(object data)
        {
            if (data == null) return null;

            // 处理字符串类型（基础类型，不需要递归）
            if (data is string) return data;

            // 处理值类型（int, decimal等，不需要递归）
            if (data.GetType().IsValueType) return data;

            // 处理集合情况
            if (data is System.Collections.IEnumerable enumerable)
            {
                var itemList = new List<object>();
                foreach (var item in enumerable)
                {
                    // 跳过字符串的字符枚举
                    if (item is char) continue;

                    itemList.Add(MaskSensitiveData(item));
                }

                // 保持原始集合类型（如List<T>）
                if (data.GetType().IsGenericType)
                {
                    var listType = typeof(List<>).MakeGenericType(data.GetType().GetGenericArguments()[0]);
                    var typedList = (System.Collections.IList)Activator.CreateInstance(listType);
                    foreach (var item in itemList) typedList.Add(item);
                    return typedList;
                }

                return itemList;
            }

            // 处理单个对象
            return MaskSingleItem(data);
        }

        /// <summary>
        /// 处理单个对象的脱敏
        /// </summary>
        private object MaskSingleItem(object item)
        {
            if (item == null) return null;

            var properties = item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var property in properties)
            {
                // 跳过索引器属性
                if (property.GetIndexParameters().Length > 0) continue;

                // 检查是否有脱敏特性
                var maskAttribute = property.GetCustomAttribute<MaskAttribute>();
                var value = property.GetValue(item);

                if (maskAttribute != null && property.CanWrite)
                {
                    // 处理标记了脱敏特性的属性
                    if (value != null)
                    {
                        try
                        {
                            var maskedValue = maskAttribute.MaskValue(value?.ToString());
                            property.SetValue(item, ConvertToTargetType(maskedValue, property.PropertyType));
                        }
                        catch
                        {
                            // 脱敏失败时保留原值
                            property.SetValue(item, value);
                        }
                    }
                }
                else if (value != null)
                {
                    // 递归处理嵌套对象属性（非值类型且非字符串）
                    if (!property.PropertyType.IsValueType && property.PropertyType != typeof(string))
                    {
                        property.SetValue(item, MaskSensitiveData(value));
                    }
                }
            }
            return item;
        }

        /// <summary>
        /// 将值转换为目标属性类型
        /// </summary>
        private object ConvertToTargetType(object value, Type targetType)
        {
            if (value == null) return null;

            // 处理可空类型
            var underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            // 如果已经是目标类型
            if (underlyingType.IsInstanceOfType(value)) return value;

            // 特殊处理字符串到其他类型的转换
            if (value is string stringValue)
            {
                if (underlyingType == typeof(decimal)) return decimal.TryParse(stringValue, out var result) ? result : 0m;
                if (underlyingType == typeof(int)) return int.TryParse(stringValue, out var result) ? result : 0;
                if (underlyingType == typeof(double)) return double.TryParse(stringValue, out var result) ? result : 0d;
                // 添加其他需要的类型转换
            }
            // 默认转换
            return Convert.ChangeType(value, underlyingType);
        }
    }
}
